import { User, Call } from "../models/index.js";
import jwt from 'jsonwebtoken'; // 引入 jwt 库

export default function socketHandler(io) {
  console.log("Socket.IO server initialized");

  // 用于存储用户 ID 到 socket ID 的映射
  const userSocketMap = new Map();
  // 用于存储用户通话状态
  const userCallStatus = new Map();  // 格式: userId => { callId, partnerId }

  // 添加中间件处理用户认证和信息
  io.use(async (socket, next) => {
    const token = socket.handshake.auth.token;
    if (!token) {
      console.log("Authentication failed: No token provided");
      return next(new Error("Authentication error"));
    }

    try {
      // 解析 token，只获取用户ID
      const decoded = jwt.verify(token, process.env.JWT_SECRET);
      
      // 从数据库获取最新的用户信息
      const user = await User.findByPk(decoded.id);
      if (!user) {
        throw new Error("User not found");
      }

      // 将用户信息存储到 socket 对象中
      socket.userId = user.id;
      socket.phone = user.phone;
      socket.email = user.email;
      socket.nickname = user.nickname;
      socket.avatar = user.avatar;
      
      console.log("Socket authenticated with:", {
        userId: socket.userId,
        nickname: socket.nickname,
        phone: socket.phone,
        email: socket.email,
        avatar: socket.avatar,
      });
      next();
    } catch (error) {
      console.log("Authentication failed:", error);
      return next(new Error("Authentication failed"));
    }
  });

  io.on("connection", (socket) => {
    console.log("Client connected:", {
      socketId: socket.id,
      userId: socket.userId,
      nickname: socket.nickname,
      phone: socket.phone,
      email: socket.email,
      avatar: socket.avatar,
    });

    // 保存用户 ID 到 socket ID 的映射
    if (socket.userId) {
      userSocketMap.set(socket.userId, socket.id);
      console.log("保存用户 ID 到 socket ID 的映射", {
        userId: socket.userId,
        userIdType: typeof socket.userId,
        socketId: socket.id,
      });

      // 打印当前所有映射
      console.log(
        "当前所有用户映射:",
        Array.from(userSocketMap.entries()).map(([userId, socketId]) => ({
          userId,
          userIdType: typeof userId,
          socketId,
        }))
      );
    } else {
      console.warn("No userId provided for socket:", socket.id);
    }

    // 发起通话
    socket.on("call", async ({ targetId }) => {
      console.log("发起通话:", {
        from: socket.id,
        caller: {
          id: socket.userId,
          phone: socket.phone,
          nickname: socket.nickname,
          avatar: socket.avatar,
          email: socket.email,
        },
        targetId,
      });

      try {
        if (!socket.userId) {
          throw new Error("用户未登录");
        }

        // 检查目标用户是否在通话中
        const targetCallStatus = userCallStatus.get(Number(targetId));
        if (targetCallStatus) {
          // 目标用户正在通话中
          console.log('目标用户正在通话中', targetId);

          socket.emit("call_busy", {
            targetId,
            message: "对方正在通话中"
          });

          // 可选：通知被叫方有新的来电
          const targetSocketId = userSocketMap.get(Number(targetId));
          if (targetSocketId) {
            socket.to(targetSocketId).emit("new_call_while_busy", {
              callerId: socket.userId,
              callerName: socket.nickname,
              callerAvatar: socket.avatar
            });
          }
          return;
        }

        // 获取目标用户的 socket ID
        const targetSocketId = userSocketMap.get(Number(targetId));
        if (!targetSocketId) {
          console.log('目标用户不在线2', targetId);

          // throw new Error("目标用户不在线1");
        }

        console.log("找到目标用户 socket:", {
          targetId,
          targetSocketId,
        });

        // 获取 Wowza 流信息
        const streamInfo = {
          id: `stream-${Date.now()}`,
          webrtc_url: process.env.WOWZA_WEBRTC_URL || "wss://your-wowza-url",
        };

        // 通过targetId查询用户头像
        const targetUser = await User.findByPk(socket.userId, {
          attributes: ["id", "nickname", "avatar", "phone", "email"],
        });
        console.log("目标用户信息:", targetUser.avatar);

        if (!targetUser) {
          throw new Error("目标用户不存在");
        }

        const callId = `${socket.id}-${Date.now()}`;

        // 创建通话记录
        const call = await Call.create({
          callerId: socket.userId,
          receiverId: Number(targetId),
          callId,
          startTime: new Date(),
          callType: "normal",
          status: "missed", // 默认为未发送
        });

        // 设置超时定时器
        const timeoutTimer = setTimeout(async () => {
          console.log('更新为未接听');
          
          const currentCall = await Call.findOne({
            where: {
              callId,
              status: "missed", // 只处理还在 missed 状态的通话
            },
          });

          if (currentCall) {
            // 如果通话记录还存在且状态为 missed，说明确实未接听
            await currentCall.update({
              endTime: new Date(),
              status: "missed",
            });

            // 通知主叫方通话未接听
            const callerSocket = userSocketMap.get(socket.userId);
            if (callerSocket) {
              // 发送未接听通知
              io.to(callerSocket).emit("call_missed", {
                callId,
                target: {
                  id: targetId,
                  phone: targetUser.phone,
                  nickname: targetUser.nickname,
                  avatar: targetUser.avatar,
                },
              });

              // 发送超时提醒
              io.to(callerSocket).emit("call_timeout", {
                callId,
                message: "对方可能暂时无法接听，请稍后再试",
                target: {
                  id: targetId,
                  phone: targetUser.phone,
                  nickname: targetUser.nickname,
                  avatar: targetUser.avatar,
                }
              });
            }

            // 清理通话状态
            userCallStatus.delete(socket.userId);
            userCallStatus.delete(Number(targetId));
          }
        }, 60000); // 一分钟超时

        // 保存定时器ID，以便在需要时清除
        const callTimeout = {
          timer: timeoutTimer,
          callId
        };
        socket.callTimeout = callTimeout;

        // 发送通话请求给目标用户，使用规范化的数据格式
        socket.to(targetSocketId).emit("incoming_call", {
          callId, // 使用刚创建的通话记录ID
          from: socket.id,
          caller: {
            id: socket.userId,
            phone: socket.phone,
            email: socket.email,
            nickname: socket.nickname,
            avatar: targetUser.avatar || "",
          },
          target: {
            id: targetUser.id,
            phone: targetUser.phone,
            email: targetUser.email,
            nickname: targetUser.nickname,
            avatar: targetUser.avatar,
          },
          streamInfo: {
            id: streamInfo.id,
            webrtcUrl: streamInfo.webrtc_url,
          },
        });

        console.log("发送通话请求给目标用户", {
          targetId,
          targetSocketId,
          nickname2: targetUser.nickname,
          nicknam3: socket.nickname,
          streamId: streamInfo.id,
        });

        // 通知主叫方请求已发送
        socket.emit("call_requested", {
          targetId,
          streamInfo,
        });

        // 更新用户通话状态
        userCallStatus.set(socket.userId, { callId, partnerId: Number(targetId) });
        userCallStatus.set(Number(targetId), { callId, partnerId: socket.userId });
      } catch (error) {
        console.error("Call error:", error);
        socket.emit("call_error", { message: error.message });
      }
    });

    // 处理接听
    socket.on("answer", async ({ targetId, callId }) => {
      try {
        // 清除超时定时器
        if (socket.callTimeout && socket.callTimeout.callId === callId) {
          clearTimeout(socket.callTimeout.timer);
          socket.callTimeout = null;
        }

        if (!socket.userId) {
          throw new Error("用户未登录");
        }

        // 获取目标用户的 socket ID
        console.log("查找目标用户:", targetId);
        console.log(
          "当前映射表:",
          Array.from(userSocketMap.entries()).map(([userId, socketId]) => ({
            userId,
            userIdType: typeof userId,
            socketId,
          }))
        );

        const targetSocketId = userSocketMap.get(Number(targetId));
        console.log("找到的目标 socket:", {
          targetId,
          targetIdType: typeof targetId,
          targetSocketId,
          found: targetSocketId != null,
        });

        if (!targetSocketId) {
          throw new Error("目标用户不在线2");
        }

        // 更新通话记录为已接听
        await Call.update(
          {
            status: "answered",
            startTime: new Date(), // 更新实际开始时间
          },
          {
            where: { callId },
          }
        );

        socket.to(targetSocketId).emit("call_answered", {
          from: socket.id,
          answerer: {
            id: socket.userId,
            phone: socket.phone,
            nickname: socket.nickname,
            avatar: socket.avatar,
          },
        });
      } catch (error) {
        console.error("Answer error:", error);
        socket.emit("answer_error", { message: error.message });
      }
    });

    // 处理拒绝
    socket.on("reject", async ({ targetId, callId }) => {
      try {
        // 清除超时定时器
        if (socket.callTimeout && socket.callTimeout.callId === callId) {
          clearTimeout(socket.callTimeout.timer);
          socket.callTimeout = null;
        }

        console.log("处理拒绝接听:", {
          from: socket.id,
          user: {
            id: socket.userId,
            phone: socket.phone,
            nickname: socket.nickname,
            avatar: socket.avatar,
          },
          targetId,
          callId,
        });

        // 查找通话记录
        const call = await Call.findOne({
          where: { callId },
        });

        if (!call) {
          console.error("未找到通话记录:", callId);
          return;
        }

        // 更新通话记录为已拒绝
        const endTime = new Date();
        await call.update({
          status: "rejected",
          endTime,
        });

        // 获取主叫方的 socket ID（这里的 callerId 是发起通话的人）
        const callerSocketId = userSocketMap.get(Number(targetId));

        if (callerSocketId) {
          console.log("通知主叫方通话被拒绝:", {
            callerSocketId,
            callId,
          });
          // 通知主叫方（发起通话的人）通话被拒绝
          socket.to(callerSocketId).emit("call_rejected", {
            callId,
            user: {
              id: socket.userId,
              phone: socket.phone,
              nickname: socket.nickname,
              avatar: socket.avatar,
            },
          });
        } else {
          console.log("主叫方不在线，无法通知");
        }

        // 清除通话状态
        userCallStatus.delete(socket.userId);
        userCallStatus.delete(Number(targetId));
      } catch (error) {
        console.error("处理拒绝通话时出错:", error);
      }
    });

    // 处理挂断
    socket.on("hangup", async ({ targetId, callId, type }) => {
      try {
        // 清除超时定时器
        if (socket.callTimeout && socket.callTimeout.callId === callId) {
          clearTimeout(socket.callTimeout.timer);
          socket.callTimeout = null;
        }

        // 获取目标用户的 socket ID
        const targetSocketId = userSocketMap.get(Number(targetId));
        console.log("通话取消请求给目标用户", targetSocketId);

        if (targetSocketId) {
          // 更新通话记录
          // if (callId) {
          //   const endTime = new Date();
          //   const call = await Call.findOne({ where: { callId } });

          //   if (call) {
          //     const duration = Math.floor(
          //       (endTime - new Date(call.startTime)) / 1000
          //     );
          //     await call.update({
          //       endTime,
          //       duration,
          //       status: "answered",
          //     });
          //   }
          // }
          // if (type === "play") {
          //   // 查找通话记录
          //   const call = await Call.findOne({
          //     where: { callId },
          //   });
          //   if (call) {
          //     // 更新通话记录为已拒绝
          //     const endTime = new Date();
          //     await call.update({
          //       status: "rejected",
          //       endTime,
          //     });
          //   }
          // }

          socket.to(targetSocketId).emit("call_ended", {
            from: socket.id,
            user: {
              id: socket.userId,
              phone: socket.phone,
              nickname: socket.nickname,
              avatar: socket.avatar,
            },
          });

          // 清除通话状态
          userCallStatus.delete(socket.userId);
          userCallStatus.delete(Number(targetId));
        }
      } catch (error) {
        console.error("Call hangup error:", error);
      }
    });

    // 心跳检测
    socket.on("ping", () => {
      console.log("Ping received from:", socket.id);
      socket.emit("pong");
    });

    // 断开连接时清理映射
    socket.on("disconnect", () => {
      console.log("Client disconnected:", socket.id);
      if (socket.userId) {
        // 清理用户映射
        userSocketMap.delete(socket.userId);
        
        // 如果用户在通话中，清理通话状态
        const callStatus = userCallStatus.get(socket.userId);
        if (callStatus) {
          const { partnerId } = callStatus;
          userCallStatus.delete(socket.userId);
          userCallStatus.delete(partnerId);
          
          // 通知通话对方，连接已断开
          const partnerSocketId = userSocketMap.get(partnerId);
          if (partnerSocketId) {
            io.to(partnerSocketId).emit("call_disconnected", {
              userId: socket.userId,
              reason: "对方连接已断开"
            });
          }
        }
      }
    });

    // 错误处理
    socket.on("error", (error) => {
      console.error("Socket error:", {
        socketId: socket.id,
        error: error.message,
      });
      socket.emit("error", { message: "发生错误，请重新连接" });
    });

    // P2P视频通话相关事件
    // 发起P2P通话
    socket.on("p2p_call", async ({ targetId }) => {
      console.log("发起P2P通话:", {
        from: socket.id,
        caller: {
          id: socket.userId,
          phone: socket.phone,
          nickname: socket.nickname,
          avatar: socket.avatar,
        },
        targetId,
      });

      try {
        if (!socket.userId) {
          throw new Error("用户未登录");
        }

        const targetSocketId = userSocketMap.get(Number(targetId));
        if (!targetSocketId) {
          throw new Error("目标用户不在线3");
        }

        const callId = `p2p-${socket.id}-${Date.now()}`;
        console.log("发起P2P通话:", targetSocketId);

        // 发送P2P通话请求给目标用户
        socket.to(targetSocketId).emit("p2p_incoming_call", {
          callId,
          from: socket.id,
          caller: {
            id: socket.userId,
            phone: socket.phone,
            nickname: socket.nickname,
            avatar: socket.avatar,
          },
        });

        // 通知主叫方请求已发送
        socket.emit("p2p_call_requested", {
          callId,
          targetId,
        });
      } catch (error) {
        console.error("P2P Call error:", error);
        socket.emit("p2p_call_error", { message: error.message });
      }
    });

    // 处理 SDP offer
    socket.on("p2p_offer", ({ targetId, callId, sdp }) => {
      console.log("收到P2P offer:", {
        from: socket.id,
        targetId,
        callId,
      });

      const targetSocketId = userSocketMap.get(Number(targetId));
      if (targetSocketId) {
        socket.to(targetSocketId).emit("p2p_offer", {
          callId,
          from: socket.id,
          sdp,
        });
      }
    });

    // 处理 SDP answer
    socket.on("p2p_answer", ({ targetId, callId, sdp }) => {
      console.log("收到P2P answer:", {
        from: socket.id,
        targetId,
        callId,
      });

      const targetSocketId = userSocketMap.get(Number(targetId));
      if (targetSocketId) {
        socket.to(targetSocketId).emit("p2p_answer", {
          callId,
          from: socket.id,
          sdp,
        });
      }
    });

    // 处理 ICE candidate
    socket.on("p2p_ice_candidate", ({ targetId, callId, candidate }) => {
      console.log("收到P2P ICE candidate:", {
        from: socket.id,
        targetId,
        callId,
      });

      const targetSocketId = userSocketMap.get(Number(targetId));
      if (targetSocketId) {
        socket.to(targetSocketId).emit("p2p_ice_candidate", {
          callId,
          from: socket.id,
          candidate,
        });
      }
    });

    // 处理P2P通话接听
    socket.on("p2p_accept", ({ targetId, callId }) => {
      console.log("P2P通话被接听:", {
        from: socket.id,
        targetId,
        callId,
      });

      const targetSocketId = userSocketMap.get(Number(targetId));
      if (targetSocketId) {
        socket.to(targetSocketId).emit("p2p_accepted", {
          callId,
          from: socket.id,
          answerer: {
            id: socket.userId,
            phone: socket.phone,
            nickname: socket.nickname,
            avatar: socket.avatar,
          },
        });
      }
    });

    // 处理P2P通话拒绝
    socket.on("p2p_reject", ({ targetId, callId }) => {
      console.log("P2P通话被拒绝:", {
        from: socket.id,
        targetId,
        callId,
      });

      const targetSocketId = userSocketMap.get(Number(targetId));
      if (targetSocketId) {
        socket.to(targetSocketId).emit("p2p_rejected", {
          callId,
          from: socket.id,
          user: {
            id: socket.userId,
            phone: socket.phone,
            nickname: socket.nickname,
            avatar: socket.avatar,
          },
        });
      }
    });

    // 处理P2P通话挂断
    socket.on("p2p_hangup", ({ targetId, callId }) => {
      console.log("P2P通话挂断:", {
        from: socket.id,
        targetId,
        callId,
      });

      const targetSocketId = userSocketMap.get(Number(targetId));
      if (targetSocketId) {
        socket.to(targetSocketId).emit("p2p_hangup", {
          callId,
          from: socket.id,
          user: {
            id: socket.userId,
            phone: socket.phone,
            nickname: socket.nickname,
            avatar: socket.avatar,
          },
        });
      }
    });
  });

  // 监听服务器级别的事件
  io.on("error", (error) => {
    console.error("Socket.IO server error:", error);
  });
}
